package org.ccay.async.config;

import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import org.ccay.core.log.ILogger;
import org.ccay.core.log.CcayLoggerFactory;
import org.ccay.core.util.StringUtil;

/**
 *  消息处理器的Xml配置解析器
 *  	
 * 
 * @since Dec 13, 2011
 */
public class MessageProcessorConfigParser extends MessageConfigParser {
	
	/** 日志记录器 **/
	private ILogger logger = CcayLoggerFactory.getLogger(MessageProcessorConfigParser.class);
	
	/** processor常量 **/
	private static final String MESSAGE_PROCESSOR_ATTRIBUTE = "processor";
	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
	 */
	@Override
	protected Class<?> getBeanClass(Element arg0) {
		return MessageProcessorConfig.class;
	}

	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#doParse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext, org.springframework.beans.factory.support.BeanDefinitionBuilder)
	 */
	@Override
	protected void doParse(Element element, ParserContext ctx, BeanDefinitionBuilder bean) {
		super.doParse(element, ctx, bean);
		
		parseMessageProcessor(element, ctx, bean);
	}
	
	/**
	 * 解析processor元素
	 * 
	 * 
	 * @since Dec 12, 2011
	 * @param element
	 * @param ctx
	 * @param bean
	 */
	private void parseMessageProcessor(Element element, ParserContext ctx, BeanDefinitionBuilder bean) {
		// 首先检查processor属性
		String processorClass = element.getAttribute(MESSAGE_PROCESSOR_ATTRIBUTE);
		if(!StringUtil.isNullOrEmpty(processorClass)) {
			try {
				Object processor = loadClass(processorClass).newInstance();
				bean.addPropertyValue(MESSAGE_PROCESSOR_ATTRIBUTE, processor);
				return;
			} catch (Exception e) {
				throw new FatalBeanException("Could not load class: "+processorClass, e);
			}
		}
		
		// 检查processor元素
		Object processor = ctx.getDelegate().parsePropertyValue(element, bean.getBeanDefinition(), null);
		bean.addPropertyValue(MESSAGE_PROCESSOR_ATTRIBUTE, processor);
	}
	
	/**
	 * 加载指定的类。
	 * 尝试顺序如下：
	 * 1. Thread.currentThread().getContextClassLoader()
	 * 2. Class.forName()
	 * 
	 * 
	 * @since Dec 12, 2011
	 * @param className
	 * @param callingClass
	 * @return
	 */
	private Class<?> loadClass(String className) throws ClassNotFoundException {
		try {
			ClassLoader cl = Thread.currentThread().getContextClassLoader();
			if(cl != null) {
				return cl.loadClass(className);
			}
		} catch (ClassNotFoundException e) {
			// do nothing, try other ways.
			logger.debug("Can't load "+className+" class from thread's context classloader");
		}
		
		try {
			return Class.forName(className);
		} catch (ClassNotFoundException e) {
			return MessageConfig.class.getClassLoader().loadClass(className);
		}
	}

}
